package com.atguigu.gmall.cart.interceptor;

import com.atguigu.gmall.cart.vo.UserInfo;
import com.atguigu.gmall.common.utils.CookieUtils;
import com.atguigu.gmall.common.utils.JwtUtils;
import com.atguigu.gmall.common.utils.RsaUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/*
    登录状态处理的拦截器：(已登录获取userId，未登录获取userKey)
            拦截所有的购物车的请求

         将userId和userKey传递给后续的接口方法使用

 */
@Component
public class LoginInterceptor implements HandlerInterceptor {
    /*
        HashMap
        List
        LoginInterpetor拦截器 访问cart项目时，所有的请求都会被拦截处理
        服务器处理请求时，每个请求对应一个线程，LoginInterceptor的成员变量是多线程共享的变量(需要考虑线程安全)
     */
//    private static ConcurrentHashMap<Thread , Object> map = new ConcurrentHashMap<>();//借助map中的线程对象作为key获取map中的值
    private static final ThreadLocal<UserInfo> THREAD_LOCAL = new ThreadLocal<>();//使用threadLocal对象作为键获取thread对象中的map中的值
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //如果客户端cookie中包含(userKey=uuid)获取userKey传递给后续的业务
        //如果客户端cookie中包含(GMALL-TOKEN=jwttoken) 获取token中的userId传递给后续的业务

        String userKey = CookieUtils.getCookieValue(request, "userKey");
        if(StringUtils.isEmpty(userKey)){
            //userKey不存在 为客户端分配未登录的userKey  并且将userKey存到cookie中交给客户端
            // 保证userKey的长度可以存到数据库表中
            userKey = UUID.randomUUID().toString().replace("-","").substring(0,20);
            CookieUtils.setCookie(request,response,"userKey",userKey,100*32*60*60);
        }
        UserInfo userInfo = new UserInfo();
        userInfo.setUserKey(userKey);
        //获取userId
        try {
            String token = CookieUtils.getCookieValue(request, "GMALL-TOKEN");
            if(StringUtils.isNotBlank(token)){
                Map<String, Object> map = JwtUtils.getInfoFromToken(token, RsaUtils.getPublicKey("F:\\keys\\rsa.pub"));
                //将已登录的userId传给后续的业务
                userInfo.setUserId(map.get("userId").toString());
            }
        } catch (Exception e) {//用户未登录或者登陆状态失效
//            e.printStackTrace();
        }
        THREAD_LOCAL.set(userInfo);
        return true;//true放行请求给目标接口方法
    }

    public static UserInfo getUserInfo(){
        return THREAD_LOCAL.get();
    }
    //当视图解析完成 请求响应即将结束前执行: 移除ThreadLocal中的共享数据，避免内存泄露
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        THREAD_LOCAL.remove();
    }
}
